package com.lagou.edu.utils;

import com.lagou.edu.annotation.Autowired;
import com.lagou.edu.annotation.Service;
import com.lagou.edu.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class AnnotationBeanFactory {

    private static final ConcurrentHashMap<String, Object> beans = new ConcurrentHashMap<String, Object>();

    public static void init(String packageName) throws Exception{
        // 使用Reflections的时候会出问题
//        Reflections f = new Reflections("com.lagou.edu");
        //1.使用java反射机制扫包，获取当前包下所有类
        List<Class<?>> classes = ClassUtil.getClasses(packageName);
        System.out.println("初始化");
        //2.判断类上面是否有注解,返回一个map集合，里面包含了，所有带ExtService注解的类的信息
        ConcurrentHashMap<String,Object> classHasExtServiceAnnotation = findClassIsHasAnnotation(classes);
        if (classHasExtServiceAnnotation == null || classHasExtServiceAnnotation.isEmpty()){
            System.out.println("该包下所有类都没有ExtServiceAnnotation");
            throw new Exception("该包下所有类都没有ExtServiceAnnotation");
        }


        for(Map.Entry<String, Object> a:beans.entrySet()){
            Object val = a.getValue();
            Class aClass = val.getClass();
            //获取属性集合
            Field[] fields = aClass.getDeclaredFields();
            //遍历属性，若持有Autowired注解则注入
            for (Field field : fields) {
                if (field.isAnnotationPresent(Autowired.class)
                        &&field.getAnnotation(Autowired.class).required()) {
                    String[] names = field.getType().getName().split("\\.");
                    String name = names[names.length - 1];
                    Object object = beans.get(toLowerCaseFirstOne(name));
                    if (!field.isAccessible())
                        field.setAccessible(true);
                    try {
                        field.set(val, object);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();

                    }
                }
            }
            //Transactional注解的判断
            if(aClass.isAnnotationPresent(Transactional.class)){
                Transactional annotation = (Transactional) aClass.getAnnotation(Transactional.class);
                String value = annotation.value();
                //获取代理工厂
                ProxyFactoryUtil proxyFactory = (ProxyFactoryUtil) beans.get("proxyFactory");
                if(value != null && "cglib".equals(value)){
                    val = proxyFactory.getCglibProxy(val);
                }else{
                    val = proxyFactory.getJdkProxy(val);
                }
            }

            beans.put(a.getKey(),val);
        }

    }

    public static ConcurrentHashMap<String, Object> findClassIsHasAnnotation(List<Class<?>> classes) throws IllegalAccessException, InstantiationException {
        for (Class<?> classInfo:classes) {
            //判断类上是否有自定义ExtService注解
            Service annotation = classInfo.getAnnotation(Service.class);
            if (annotation !=null){
                //beans(类名小写,classInfo)
                //获取当前类名
                String className = classInfo.getSimpleName();
                //将类名首字母变为小写
                String beanID =annotation.value();
                System.out.println("beanID = " + beanID);
                //如果当前类上有ExtService注解，将该类的信息，添加到map集合
                beans.put(beanID,classInfo.newInstance());
            }
        }
        return beans;
    }

    // 首字母转小写
    public static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    public static Object getBean(String beanName) {
        return beans.get(beanName);
    }

}
